package lee.vioson.ebook.viewmodels

import android.os.CountDownTimer
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import com.laiyifen.lyftoast.toast
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import lee.vioson.composecommon.base.mvi.BaseViewModel
import lee.vioson.composecommon.base.mvi.Reducer
import lee.vioson.composecommon.base.mvi.UiEvent
import lee.vioson.composecommon.base.mvi.UiState
import lee.vioson.ebook.data.AppContainer
import lee.vioson.ebook.ui.AppDestinations

/**
 *Author:viosonlee
 *Date:2023/6/9
 *DESCRIPTION:
 */
class OtpVeriViewModel(private val appContainer: AppContainer, private val type: Int) :
    AppViewModel<OtpVeriViewModel.State, OtpVeriViewModel.Event>(appContainer.appEvent) {

    private val reducer = SubReducer(State())

    override val state: StateFlow<State>
        get() = reducer.state

    override fun sendEvent(event: Event) {
        reducer.sendEvent(event)
    }


    /**
     * resend verification code
     */

    fun resend(email: String) {
        sendEmailCode(email)
    }

    /**
     * send email code
     */
    fun sendEmailCode(email: String) =
        appContainer.registerRepository.sendEmailCode(appContainer.uniqueId, email)
            .catch { handleException(it) }
            .onStart { showLoading() }
            .onCompletion { dismissLoading() }
            .onEach { startCountdown() }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
            .launchIn(viewModelScope)


    fun commit(
        email: String,
        password: String?,
        emailCode: String,
        areaCode: String,
        language: String,
        navHostController: NavHostController
    ) {
        if (type == 0) {
            register(email, password, emailCode, areaCode, language, navHostController)
                .launchIn(viewModelScope)
        }
        if (type == 1) {
            setPassword(email, password, emailCode, navHostController).launchIn(viewModelScope)
        }
    }

  private  fun setPassword(
        email: String,
        password: String?,
        emailCode: String,
        navHostController: NavHostController
    ) = appContainer.registerRepository.setPassword(
        appContainer.uniqueId,
        email,
        password ?: "",
        emailCode
    )
        .catch { handleException(it) }
        .onEach {
            //password set up success
            appContainer.context.toast("password set up successful !")
            navHostController.navigate(AppDestinations.MAIN_ROUTE) {
                popUpTo(navHostController.graph.findStartDestination().id) {
                    inclusive = true
                }
            }
        }
        .onStart { showLoading() }
        .onCompletion { dismissLoading() }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)

    private fun register(
        email: String,
        password: String?,
        emailCode: String,
        areaCode: String,
        language: String,
        navHostController: NavHostController
    ) = appContainer.registerRepository.register(
        appContainer.uniqueId, email, password ?: "",
        emailCode, customerSource = appContainer.customerSource,
        areaCode, language
    )
        .catch { handleException(it) }
        .onEach {
            //register success
            appContainer.context.toast("sign up successful !")
            navHostController.navigate(AppDestinations.MAIN_ROUTE) {
                popUpTo(navHostController.graph.findStartDestination().id) {
                    inclusive = true
                }
            }
        }
        .onStart { showLoading() }
        .onCompletion { dismissLoading() }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)

    var isCountdownCompleted by mutableStateOf(false)

    private val totalWaitTime = 60 * 1000L
    private var countDownTimer: CountDownTimer? = null

    private fun startCountdown() {
        isCountdownCompleted = false
        sendEvent(Event.OnStartCountDownTime)
        countDownTimer = object : CountDownTimer(totalWaitTime, 1000L) {
            override fun onTick(millisUntilFinished: Long) {
                sendEvent(Event.OnCountDownTime)
            }

            override fun onFinish() {
                isCountdownCompleted = true
                countDownTimer = null
            }

        }
        countDownTimer?.start()
    }


    private class SubReducer(initialState: State) :
        Reducer<State, Event>(initialState) {
        private val maxSecond = 59
        override fun reduce(oldState: State, event: Event) {
            when (event) {
                is Event.OnOtpTxtChange -> {
                    setState(oldState.copy(otpText = event.str, completed = event.completed))
                }

                is Event.OnCountDownTime -> {
                    val lastSecond = oldState.lastSecond - 1
                    setState(oldState.copy(lastSecond = lastSecond))
                }

                is Event.OnStartCountDownTime -> {
                    setState(oldState.copy(lastSecond = maxSecond))
                }
            }
        }
    }


    sealed class Event : UiEvent {
        data class OnOtpTxtChange(val str: String, val completed: Boolean) : Event()
        object OnStartCountDownTime : Event()
        object OnCountDownTime : Event()
    }

    data class State(
        val otpText: String = "",
        val completed: Boolean = otpText.length == 4,
        val error: String? = null,
        val lastSecond: Int = -1
    ) : UiState
}

